﻿// TODO: add designer to ensure the target allow multiple selection

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Diagnostics.CodeAnalysis;

namespace DevIsMagic.ExtendedListBox
{
    /// <summary>
    /// Summary description for ListBoxExtenderControl
    /// </summary>
    [TargetControlType(typeof(ListBox))]
    // [Designer(typeof(Design.ListBoxExtenderControlDesigner))]
    public class ListBoxExtenderControl : ExtenderControl
    {
        /// <summary>
        /// Default
        /// </summary>
        private const string DEFAULT_CATALOGVALUESLABEL = "Available values";
        private const string DEFAULT_CONTAINERCSSCLASS = "extendedListBoxContainer";
        private const string DEFAULT_SELECTEDVALUESLABEL = "Selected values";


        /// <summary>
        /// Create a new instance of ListBoxExtenderControl
        /// </summary>
        public ListBoxExtenderControl()
        {
            this.ContainerCssClass = DEFAULT_CONTAINERCSSCLASS;
            this.SelectedValuesLabel = DEFAULT_SELECTEDVALUESLABEL;
            this.CatalogValuesLabel = DEFAULT_CATALOGVALUESLABEL;
        }

        /// <summary>
        /// Gets or sets the label that is located on top of available values
        /// </summary>
        [DefaultValue(DEFAULT_CATALOGVALUESLABEL)]
        public string CatalogValuesLabel { get; set; }

        /// <summary>
        /// Gets or sets the css class of the container div that is generated.
        /// You can customize the appearence of your control by creating css rules that have
        /// its selection path starting with this css class.
        /// </summary>
        /// <remarks> The default value for this property is <c>extendedListBoxContainer</c>.
        /// If you leave the field unmodified, the following css file is automatically linked
        /// to the page and can be used as a template for customizing the extender :
        /// <code>.extendedListBoxContainer
        ///{
        ///    width: 300px;
        ///    height: 120px;
        ///}
        ///.extendedListBoxContainer label
        ///{
        ///    height: 20px;
        ///}
        ///.extendedListBoxContainer div
        ///{
        ///    text-align: center;
        ///    height: 100%;
        ///    float: left;
        ///    width: 138px;
        ///    float: left;
        ///}
        ///.extendedListBoxContainer select
        ///{
        ///    width: 100%;
        ///    height: 100px;
        ///}
        ///.extendedListBoxContainer .buttons
        ///{
        ///    width: 24px;
        ///    height: 100px;
        ///    padding-top: 16px;
        ///}
        ///.extendedListBoxContainer img
        ///{
        ///    margin: 2px 4px 2px 4px;
        ///}
        ///</code>
        /// </remarks>
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        public string ContainerCssClass { get; set; }

        /// <summary>
        /// Gets or sets the image url to use for the "Move all to selected" button. If no url
        /// is specified, a embedded default image will be used.
        /// </summary>
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        [SuppressMessage("Microsoft.Design","CA1056", Justification="We can't use UrlEditor with an Uri object.")]
        public string MoveAllToSelectedImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the image url to use for the "Move all to un selected" button. If no url
        /// is specified, a embedded default image will be used.
        /// </summary>
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        [SuppressMessage("Microsoft.Design", "CA1056", Justification = "We can't use UrlEditor with an Uri object.")]
        public string MoveAllToUnselectedImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the image url to use for the "Move to selected" button. If no url
        /// is specified, a embedded default image will be used.
        /// </summary>
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        [SuppressMessage("Microsoft.Design", "CA1056", Justification = "We can't use UrlEditor with an Uri object.")]
        public string MoveToSelectedImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the image url to use for the "Move to unselected" button. If no url
        /// is specified, a embedded default image will be used.
        /// </summary>
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        [SuppressMessage("Microsoft.Design", "CA1056", Justification = "We can't use UrlEditor with an Uri object.")]
        public string MoveToUnselectedImageUrl { get; set; }

        /// <summary>
        /// Gets or sets the label that is located on top of selected values
        /// </summary>
        [DefaultValue(DEFAULT_SELECTEDVALUESLABEL)]
        public string SelectedValuesLabel { get; set; }



        /// <summary>
        /// Registers the System.Web.UI.ScriptDescriptor objects for the control.
        /// </summary>
        /// <param name="targetControl">The <see cref="System.Web.UI.WebControls.ListBox"/> control to which the extender is associated.</param>
        /// <returns>An enumeration of <see cref="System.Web.UI.ScriptDescriptor"/>objects</returns>
        protected override IEnumerable<ScriptDescriptor>
                GetScriptDescriptors(System.Web.UI.Control targetControl)
        {
            ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor(
                "DevIsMagic.ExtendedListBox.ListBoxExtenderBehavior",
                targetControl.ClientID
                );

            descriptor.AddProperty(
                "moveToSelectedImageUrl",
                !string.IsNullOrEmpty(MoveToSelectedImageUrl) ?
                    ResolveClientUrl(MoveToSelectedImageUrl) :
                    Page.ClientScript.GetWebResourceUrl(typeof(ListBoxExtenderControl), "DevIsMagic.ExtendedListBox.Resources.RightArrowHS.png")
                );

            descriptor.AddProperty(
                "moveToUnselectedImageUrl",
                !string.IsNullOrEmpty(MoveToUnselectedImageUrl) ?
                    ResolveClientUrl(MoveToUnselectedImageUrl) :
                    Page.ClientScript.GetWebResourceUrl(typeof(ListBoxExtenderControl), "DevIsMagic.ExtendedListBox.Resources.LeftArrowHS.png")
                );

            descriptor.AddProperty(
                "moveAllToSelectedImageUrl",
                !string.IsNullOrEmpty(MoveAllToSelectedImageUrl) ?
                    ResolveClientUrl(MoveAllToSelectedImageUrl) :
                    Page.ClientScript.GetWebResourceUrl(typeof(ListBoxExtenderControl), "DevIsMagic.ExtendedListBox.Resources.DoubleRightArrowHS.png")
                );

            descriptor.AddProperty(
                "moveAllToUnselectedImageUrl",
                !string.IsNullOrEmpty(MoveAllToUnselectedImageUrl) ?
                    ResolveClientUrl(MoveAllToUnselectedImageUrl) :
                    Page.ClientScript.GetWebResourceUrl(typeof(ListBoxExtenderControl), "DevIsMagic.ExtendedListBox.Resources.DoubleLeftArrowHS.png")
                );

            descriptor.AddProperty(
                "containerCssClass",
                ContainerCssClass
                );

            descriptor.AddProperty(
                "catalogValuesLabel",
                CatalogValuesLabel
                );

            descriptor.AddProperty(
                "selectedValuesLabel",
                SelectedValuesLabel
                );
            yield return descriptor;
        }

        /// <summary>
        ///  Generate the script reference to include the client behavior.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable<ScriptReference>
                GetScriptReferences()
        {
            yield return new ScriptReference(
                "DevIsMagic.ExtendedListBox.ListBoxExtenderBehavior.js",
                this.GetType().Assembly.FullName
                );
        }

        /// <summary>
        /// When the page is loading, register if required the default css file.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // Register default css file if required
            if (ContainerCssClass == DEFAULT_CONTAINERCSSCLASS)
            {
                LiteralControl cssInclude = new LiteralControl(string.Format(
                    System.Globalization.CultureInfo.InvariantCulture,
                    "<link rel='stylesheet' type='text/css' href='{0}' />",
                    Page.ClientScript.GetWebResourceUrl(typeof(ListBoxExtenderControl), "DevIsMagic.ExtendedListBox.Resources.ExtendedListBoxDefaultStyle.css")
                    ));

                // If possible, add to the head, otherwise, to the page
                ((Control)Page.Header ?? Page).Controls.AddAt(0, cssInclude);
            }
        }
    }
}